﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Utils.Drawing;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Utils.Debugging
{
    public class ProfilerItem
    {
        const float textXAdd = 15;
        const float textYAdd = 13;

        /*
         * Fields
         */
        string name;
        double elapsedTime;
        double safedElapsedTime;
        double perOfParent;
        double perOfTotal;
        Stopwatch stopwatch;
        ProfilerItem parent;
        List<ProfilerItem> childs = new List<ProfilerItem>();
        SpriteFont font;
        TextField txtName;
        TextField txtValue;
        bool updateByDraw;

        /*
         * Properties
         */
        public string Name { get { return name; } }
        public ProfilerItem Parent { get { return parent; } }
        public bool UpdateByDraw { get { return updateByDraw; } set { updateByDraw = value; } }

        public double TotalElapsedTime
        {
            set
            {
                if (value > 0)
                {
                    perOfTotal = safedElapsedTime * 100f / value;
                }

                foreach (ProfilerItem p in childs)
                {
                    p.TotalElapsedTime = value;
                }
            }
        }

        public double SafedElapsedTime { get { return safedElapsedTime; } }

        public ProfilerItem(string name, SpriteFont font, ProfilerItem parent)
        {
            this.name = name;
            this.font = font;
            this.parent = parent;
            if (parent != null)
            {
                parent.AddChild(this);
            }

            stopwatch = new Stopwatch();

            txtName = new TextField(font, 32);
            txtName.Origin = TextField.ORIGIN_TOP_LEFT;

            txtValue = new TextField(font, 64);
            txtValue.Origin = TextField.ORIGIN_TOP_LEFT;
        }

        public void AddChild(ProfilerItem profiler)
        {
            childs.Add(profiler);
        }

        public ProfilerItem Find(string name)
        {
            foreach(ProfilerItem p in childs)
            {
                if (String.Equals(p.Name, name))
                {
                    return p;
                }
            }
            return null;
        }

        public void Start()
        {
            stopwatch.Reset();
            stopwatch.Start();
        }

        public void Stop()
        {
            elapsedTime += stopwatch.Elapsed.TotalSeconds;
        }

        public void Evaluate()
        {
            safedElapsedTime = elapsedTime;
            elapsedTime = 0;

            if (parent != null && parent.SafedElapsedTime > 0)
            {
                perOfParent = safedElapsedTime * 100f / parent.SafedElapsedTime;
            }

            foreach (ProfilerItem p in childs)
            {
                p.Evaluate();
            }
        }

        public void Draw(SpriteRenderer renderer, float currentXPos, ref float currentYPos, float valueOffset, float height)
        {
            txtName.Text.Set(name).Append(":");
            txtName.Pos = new Vector2(currentXPos, currentYPos);
            txtName.Draw(renderer);

            txtValue.Text.Set(safedElapsedTime, 5).Append("  -  ");
            if (perOfTotal < 10f)
            {
                txtValue.Text.Append("  ");
            }
            txtValue.Text.Append(perOfTotal, 4).Append(" %  -  ");
            if (perOfParent < 10f)
            {
                txtValue.Text.Append("  ");
            }
            txtValue.Text.Append(perOfParent, 2).Append(" %");
            txtValue.Pos = new Vector2(currentXPos + valueOffset, currentYPos);
            txtValue.Draw(renderer);

            currentYPos += textYAdd;

            foreach (ProfilerItem p in childs)
            {
                p.Draw(renderer, currentXPos + textXAdd, ref currentYPos, valueOffset, height);
            }
        }
    }
}
